#pragma once

#include<winsock2.h>
#include <mysql.h>
#pragma comment (lib,"libmysql.lib")

namespace gtl
{

namespace db
{

class mysql
{
public:
	class results;

public:
	mysql()
	{
		m_mysql = mysql_init(0);
	}

	virtual ~mysql()
	{
		if(m_mysql != NULL)
			mysql_close(m_mysql);
	}

public:
	bool connect(const char* server, const char* user, const char* passwd, const char* db, unsigned int port = 3306)
	{
		if(m_mysql == NULL || user == NULL || passwd == NULL || db == NULL)
			return false;

		return mysql_real_connect(m_mysql, server, user, passwd, db, port, NULL, 0) != NULL;
	}

	results select(const char* sql)
	{
		if(m_mysql == NULL || sql == NULL)
			return NULL;

		if(mysql_query(m_mysql, sql) != 0)
			return NULL;

		return mysql_store_result(m_mysql);
	}

public:
	class results
	{
	public:
		class iterator;

	public:
		results(MYSQL_RES* rs)
			: m_end(NULL, NULL, 0)
			, m_rs(rs)
		{
			if(m_rs != NULL)
			{
				m_rows = mysql_num_rows(m_rs);
				m_cols = mysql_num_fields(m_rs);
			}
			else
			{
				m_rows = 0;
				m_cols = 0;
			}
		}

		results(const results& rs)
			: m_end(rs.m_end)
			, m_rs(rs.m_rs)
			, m_rows(rs.m_rows)
			, m_cols(rs.m_cols)
		{
		}

		~results()
		{
			//if(m_rs != NULL)
			//	mysql_free_result(m_rs);
		}

	public:
		my_ulonglong rows()
		{
			return m_rows;
		}

		my_ulonglong cols()
		{
			return m_cols;
		}

		iterator begin()
		{
			return iterator(m_rs, mysql_fetch_row(m_rs), m_cols);
		}

		const iterator& end()
		{
			return m_end;
		}

	public:
		class iterator
		{
		public:
			iterator(MYSQL_RES* rs, MYSQL_ROW row, my_ulonglong cols)
			{
				m_rs = rs;
				m_row = row;
				m_cols = cols;
			}

			iterator(const iterator& it)
			{
				m_rs = it.m_rs;
				m_row = it.m_row;
				m_cols = it.m_cols;
			}

		public:
			int size()
			{
				return (int)m_cols;
			}

		public:
			iterator& operator++()
			{
				m_row = mysql_fetch_row(m_rs);
				if(m_row == NULL)
					m_rs = NULL;

				return *this;
			}

			bool operator==(const iterator& it)
			{
				return m_rs == it.m_rs && m_row == it.m_row;
			}

			bool operator!=(const iterator& it)
			{
				return m_rs != it.m_rs || m_row != it.m_row;
			}

			const char* operator[](int col)
			{
				if(m_row == NULL || col < 0 || col >= m_cols)
					return NULL;

				return m_row[col];
			}

		private:
			my_ulonglong m_cols;
			MYSQL_ROW m_row;
			MYSQL_RES* m_rs;
		}; // iterator

	private:
		my_ulonglong m_rows;
		my_ulonglong m_cols;
		MYSQL_RES* m_rs;
		iterator m_end;
	}; // results

protected:
	MYSQL* m_mysql;
}; // mysql

} // end namespace db

} // end namespace gtl